<?php
declare (strict_types = 1);

namespace App\Service\Rbac;

use App\Constants\{DefaultValue,ErrorCode,RedisKey};
use App\Dao\{AuthCompanyDao,AuthEmployeeDao,AuthOrganizationDao,AuthPermissionDao};
use App\Exception\BusinessException;
use Wuxian\WebUtils\{JwtUtils,CaptchaUtils};
use App\Utils\ApiUtils;
use Hyperf\DbConnection\Db;
use Hyperf\Di\Annotation\Inject;
use Hyperf\Redis\Redis;
use Hyperf\Utils\ApplicationContext;
use Wuxian\Rbac\Rbac;

class LoginService
{
    /**
     * @Inject
     * @var AuthEmployeeDao
     */
    protected $authEmployeeDao;
    protected $redis;
    protected $cache;
    public function __construct()
    {
        $container = ApplicationContext::getContainer();
        $this->redis = $container->get(Redis::class);
        $this->cache = $container->get(\Psr\SimpleCache\CacheInterface::class);
    }

    public function account(array $data)
    {
        // 识别是否是验证过授权码的
        $this->checkAuth($data['key'], $data['content']);
        // 验证公司名称是否存在
        $hasCompany = make(AuthCompanyDao::class)->firstByWhereTrait(
            ['name' => $data['company'],
                'is_del' => 1]);
        if ($hasCompany) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '公司名称已存在');
        }

        // 验证账号是否存在
        if (make(AuthEmployeeDao::class)->existsByWhereTrait(['account' => $data['account']])) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '该账号系统已存在');
        }
        Db::beginTransaction();
        try {
            $new_company = make(AuthCompanyDao::class)->insertGetIdTrait(
                ['name' => $data['company'],
                    'verification' => $data['verification'],
                    'add_time' => time()]);
            $organization = make(AuthOrganizationDao::class)->createTrait([
                'name' => $data['company'],
                'prefix_name' => $data['company'] . '-',
                'company_id' => $new_company,
                'pid' => 0,
                'add_time' => time()]);
            $account = ['job_number' => $data['account'],
                'account' => $data['account'],
                'organization_id' => $organization->id,
                'password' => ApiUtils::aesEnPassword($data['password']),
                'phone' => $data['phone'],
            ];
            $account = make(AuthEmployeeDao::class)->createTrait($account);
            make(AuthOrganizationDao::class)->updateByWhereTrait(['id' => $organization->id], ['employee_id' => $account->id]);
            Db::commit();
            return $data;
        } catch (\Throwable $t) {
            Db::rollBack();
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '网络异常 数据写入失败' . $t->getMessage());
        }
    }

    public function auth(string $verfication)
    {
        // TODO 校验授权码是否正确[等待总后台系统确认后更新]
        if ($verfication != 'hellokitty') {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权码不正确');
        } else {
            //把授权校验码存redis
            mt_srand();
            $key = time() . mt_rand(1, 1000000);
            $content = ApiUtils::encryption($key);
            $this->redis->setex(RedisKey::AUTH_CODE_KEY . $key, DefaultValue::AUTH_ACCOUNT_TTL, $content);
            return ['key' => $key, 'content' => $content];
        }
    }

    public function login(array $request): array
    {
        $this->checkCapcha($request['key'], (int) $request['code']);
        var_dump('验证码校验');
        $info = $this->authEmployeeDao->firstByWhereTrait(['account' => $request['name'], 'is_del' => 1]);
        var_dump('查询数据库',$info);
        if (empty($info)) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '用户名错误');
        }
        if ($info->admin_status != 1) throw  new BusinessException(ErrorCode::ERR_BUESSUS, '该账户不能登录后台');
        if (ApiUtils::aesEnPassword($request['password']) == $info->password) {
            var_dump('密码校验');
            $this->authEmployeeDao->updateByWhereTrait(['id' => $info->id], ['update_time' => time()]);
            $token = JwtUtils::authorizations([
                'uid' => $info->id,
                'name' => $info->name,
                'account' => $info->account,
                'company_id' => $info->company_id],
                config('web.admin_jwt_key'));
//            $menu = make(AuthPermissionDao::class)->searchPerByWhereId((int) $info->id);
            var_dump('token',$token);
//            $rbac = new Rbac(config('rbac.defualt'));
//            $menu = $rbac->menu($info->id);
            // 用户权限写入redis
//            $this->insertOrUpdateAuthRedis((int)$info->id);
            return ['user_id' => $info->id,
                'account' => $info->account,
                'token' => $token
//                'menu' => $menu
            ];
        }
        throw new BusinessException(ErrorCode::ERR_BUESSUS, '密码错误');
    }

    // 生成验证码
    public function verify(): array
    {
        $verify = new CaptchaUtils($this->cache);
        return $verify->generationCode();
    }

    // 校验验证码
    public function checkCapcha(string $key, int $code): bool
    {
        if (config('web.active_capcha')) {
            return true;
        }
        $verify = new CaptchaUtils($this->cache);
        $scode = $verify->verify($key,$code);
        if ($scode) {
            return true;
        }
        throw new BusinessException(ErrorCode::ERR_BUESSUS, '验证码不对');
    }

    // 授权码检测
    public function checkAuth(string $key, string $content): bool
    {
        $scode = $this->redis->get(RedisKey::AUTH_CODE_KEY . $key);
        $this->redis->del(RedisKey::AUTH_CODE_KEY . $key);
        if (!$content || !$scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权状态不存在');
        }

        if ($content != $scode) {
            throw new BusinessException(ErrorCode::ERR_BUESSUS, '授权状态错误');
        }

        return true;
    }

    // 新增或更新用户权限列表到redis
    public function insertOrUpdateAuthRedis(int $user_id)
    {
        // 查看redis是否存在用户权限数据
        $user_permission_list = $this->redis->get(RedisKey::USER_AUTH_KEY.$user_id);
        if ($user_permission_list) {
            $this->redis->del(RedisKey::USER_AUTH_KEY.$user_id);
        }
        // 根据用户id获取所有的权限
        $permiss_list = make(AuthEmployeeDao::class)->getPermissionById($user_id);
        // 写入redis
        $this->redis->set(RedisKey::USER_AUTH_KEY.$user_id,json_encode($permiss_list));
    }

}
